// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2023 Yevhen Babiichuk (DustDFG)

#include <Abracadabra/View/View.hpp>
#include <Abracadabra/View/Theme.hpp>
#include <Abracadabra/View/Tube.hpp>

namespace View
{

View::View(uint8_t tubeSize, uint8_t tubeCount, sf::RenderWindow* window)
	: IView(tubeSize, tubeCount)
	, window(window)
{
	this->theme = new Theme();

	for(size_t i = 0; i < tubeCount; ++i)
	{
		this->gridOfDots.push_back(Tube(this->tubeSize, {100 * i, 0, 100, 80 * tubeSize}));
		this->gridOfDots[i].theme = this->theme;
	}
}

View::~View()
{
}

void View::updateTube(uint8_t tubeIndex, const std::vector<uint8_t>& dots)
{
	this->gridOfDots[tubeIndex].update(dots);
}

std::optional<uint8_t> View::getTubeIndex(sf::Event& event) const
{
	for(size_t i = 0; i < tubeCount; ++i)
	{
		for(size_t j = 0; j < tubeSize; ++j)
		{
			sf::FloatRect dotBounds = this->gridOfDots[i][j].getGlobalBounds();

			if(dotBounds.contains({event.mouseButton.x, event.mouseButton.y}))
			{
				return i;
			}
		}
	}
	return std::nullopt;
}

void View::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
	for(size_t i = 0; i < tubeCount; ++i)
	{
			target.draw(this->gridOfDots[i]);
	}

	this->drawTubeTextures(target, states);

}


void View::drawTubeTextures(sf::RenderTarget& target, sf::RenderStates states) const
{
	//Draw tubes
	//Yes I draw tubes over dots. Anyway, it doesn't matter.
	//The textures don't intersects so everything is good

	for(size_t i = 0; i < tubeCount; ++i)
	{
		this->gridOfDots[i][0].setTexture(&this->theme->tubeTexture);
		this->gridOfDots[i][0].setTextureRect({0, 0, this->theme->tubePartTextureW, this->theme->tubePartTextureH});
		target.draw(this->gridOfDots[i][0]);
		for(size_t j = 1; j < (tubeSize - 1); ++j)
		{
			this->gridOfDots[i][j].setTexture(&this->theme->tubeTexture);
			this->gridOfDots[i][j].setTextureRect({0, this->theme->tubePartTextureH, this->theme->tubePartTextureW, this->theme->tubePartTextureH});
			target.draw(this->gridOfDots[i][j]);
			//target.draw(this->gridOfDots[i][j]);
		}
		this->gridOfDots[i][tubeSize - 1].setTexture(&this->theme->tubeTexture);
		this->gridOfDots[i][tubeSize - 1].setTextureRect({0, this->theme->tubePartTextureH * 2, this->theme->tubePartTextureW, this->theme->tubePartTextureH});
		target.draw(this->gridOfDots[i][tubeSize - 1]);
	}
}

void View::draw() const
{
	this->window->draw((*this));
}

}
